package conn

import (
	"log"
	"net"
	"strings"
	"time"
)

func Dial(network, addr string) (*Conn, error) {
	var c net.Conn
	var err error
	switch network {
	case "udp", "UDP":
		udpAddr, err := net.ResolveUDPAddr("udp", addr)
		if err != nil {
			return nil, err
		}
		c, err = net.DialUDP("udp", nil, udpAddr)
	default:
		c, err = net.Dial(network, addr)
	}
	if err != nil {
		return nil, dealErr(err)
	}
	log.Printf("[信息][%s] 连接%s服务成功...\n", addr, strings.ToUpper(network))
	return New(c), nil
}

func DialUDP(addr string) (*Conn, error) {
	return Dial("UDP", addr)
}

func DialTCP(addr string) (*Conn, error) {
	return Dial("tcp", addr)
}

// MustDial
// 尝试连接直至成功,1次,断开不会重连
// 采用退避重试,2s-32s,倍数增长
func MustDial(network, addr string) *Conn {
	t := time.Second
again:
	c, err := Dial(network, addr)
	if err != nil {
		if t < time.Second*30 {
			t = 2 * t
		}
		log.Printf("[错误][%s] %s,等待%s秒重试", addr, err.Error(), t)
		time.Sleep(t)
		goto again
	}
	return c
}

func MustDialTCP(addr string) *Conn {
	return MustDial("tcp", addr)
}

func MustDialUDP(addr string) *Conn {
	return MustDial("udp", addr)
}

// Redial 重试连接
func Redial(network, addr string, fn ...func(c *Conn)) *Conn {
	return MustDial(network, addr).Redial(fn...)
}

func RedialTCP(addr string, fn ...func(c *Conn)) *Conn {
	return MustDialTCP(addr).Redial(fn...)
}

func RedialUDP(addr string, fn ...func(c *Conn)) *Conn {
	return MustDialUDP(addr).Redial(fn...)
}
